package de.szut.sudoku.game;

import java.util.Observable;

import de.szut.sudoku.game.field.FieldGenerator;
import de.szut.sudoku.game.field.SudokuField;

/**
 * Class for the GameModel
 * 
 * @author dqi12huisinga
 * 
 */
public class GameModel extends Observable {
	private GameModelAction gameModelAction;
	private FieldGenerator generator;

	/**
	 * Changing the value
	 * 
	 * @param value
	 * @param xPosition
	 * @param yPosition
	 */
	public void changeValue(int value, int xPosition, int yPosition) {
		// refreshes the state on the current sudoku field
		generator.getCurrentSudokuField().getHorizontalGroups()[yPosition]
				.getBoxes().get(xPosition).setState(value);
		// notifies the UI that the game has ended if it has ended
		if (generator.gameHasEnded()) {
			gameModelAction.setState(GameModelActions.ENDGAME);
		} else {
			gameModelAction.setState(GameModelActions.CHANGEVALUE);
		}
		gameModelAction.getSudokuButtonChanger().setChangedValue(value);
		gameModelAction.getSudokuButtonChanger().setPosition(xPosition,
				yPosition);

		setChanged();
		notifyObservers(gameModelAction);
	}

	/**
	 * Generates the sudokufield
	 */
	public void generateField() {
		generator = new FieldGenerator();
		generator.generateSudokuField();
		// notifies the UI that the field has been generated
		gameModelAction.setState(GameModelActions.GENERATEFIELD);
		gameModelAction.getSudokuFieldContainer().setCurrentField(
				generator.getStartSudokuField());
		setChanged();
		notifyObservers(gameModelAction);
	}

	/**
	 * Saves the sudokufield
	 * 
	 * @param location
	 */
	public void saveFields(String location) {
		// notifies the UI that the game is supposed to get saved
		gameModelAction.setState(GameModelActions.SAVEGAME);
		gameModelAction.getSudokuFieldContainer().setCurrentField(
				generator.getCurrentSudokuField());
		gameModelAction.getSudokuFieldContainer().setStartField(
				generator.getStartSudokuField());
		gameModelAction.getSudokuFieldContainer().setGoalField(
				generator.getGoalSudokuField());
		gameModelAction.getSudokuFieldContainer().setLocation(location);
		setChanged();
		notifyObservers(gameModelAction);
	}

	/**
	 * Loads the game
	 * 
	 * @param loadedData
	 */
	public void loadGame(String[][][] loadedData) {
		generator = new FieldGenerator();
		SudokuField currentField = new SudokuField();
		// converts string arrays to sudokufields
		// Field 1
		int xIndex = 0;
		// iterates through the loaded data and refreshes the data on the field
		for (String[] currentLine : loadedData[0]) {
			int yIndex = 0;
			for (String currentElem : currentLine) {
				currentField.getHorizontalGroups()[xIndex].getBoxes()
						.get(yIndex).setState(Integer.valueOf(currentElem));
				yIndex++;
			}
			xIndex++;
		}
		generator.setCurrentSudokuField(currentField);

		SudokuField goalField = new SudokuField();
		// Field 2
		xIndex = 0;
		for (String[] currentLine : loadedData[1]) {
			int yIndex = 0;
			for (String currentElem : currentLine) {
				goalField.getHorizontalGroups()[xIndex].getBoxes().get(yIndex)
						.setState(Integer.valueOf(currentElem));
				yIndex++;
			}
			xIndex++;
		}
		generator.setGoalSudokuField(goalField);

		SudokuField startField = new SudokuField();
		// Field 3
		xIndex = 0;
		for (String[] currentLine : loadedData[2]) {
			int yIndex = 0;
			for (String currentElem : currentLine) {
				startField.getHorizontalGroups()[xIndex].getBoxes().get(yIndex)
						.setState(Integer.valueOf(currentElem));
				yIndex++;
			}
			xIndex++;
		}
		generator.setStartSudokuField(startField);

		// notifies the ui that the game is supposed to get loaded
		gameModelAction.setState(GameModelActions.LOADGAME);
		gameModelAction.getSudokuFieldContainer().setCurrentField(
				generator.getCurrentSudokuField());
		gameModelAction.getSudokuFieldContainer().setStartField(
				generator.getStartSudokuField());
		setChanged();
		notifyObservers(gameModelAction);
	}

	public GameModel() {
		gameModelAction = new GameModelAction();
	}
}
